package com.hl.socket;

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Map.Entry;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import com.hl.util.AnalysisStr;
import com.hl.util.CodeAttribute;

/**
 * 接收指令类
 * @author Administrator
 *
 */
public class SocketInput implements Runnable{
	
	private Logger log = LogManager.getLogger(SocketInput.class);
	private Socket socket;
	
	Map<String,CodeAttribute> map;
	public SocketInput(Socket socket,Map<String,CodeAttribute> map) {
		this.socket = socket;
		this.map = map;
	}
	@Override
	public void run() {
		BufferedReader bff = null;
		AnalysisStr analy = new AnalysisStr();  //创建解析指令类
		CodeAttribute code = null;
		try {
			// 从客户端获取信息
			bff = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			// 读取发来服务器信息
			String line = null;
			// 循环一直接收当前socket发来的消息
			String info = null;
			while ((info = bff.readLine()) != null) {
				try {
					code = analy.analy(info,code);  //解析
					if(code == null) {continue;}
					System.out.println(code.getClientOnlyId() + " hash值为 " + code.hashCode());
					log.info(code.getClientOnlyId() + " hash值为 " + code.hashCode());
					code.setSocket(socket);  //把socket保存
					code.setConnectionStatus(true); //客户端连接成功,设置状态
					map.put(code.getClientOnlyId(), code);//把客户端信息保存到map
					processingInstruction(code); //开始处理客户端指令
				} catch (Exception e) {
					System.out.println("字符串解析出错..." + e);
					log.error("字符串解析出错..." + e);
					break;
				}
			}
		} catch (Exception e) {
			System.out.println("客户端关闭了连接...读取客户端数据异常.");
			log.error("客户端关闭了连接...读取客户端数据异常.");
			if(socket != null && socketClose(socket,bff)) {
				System.out.println("关闭连接成功---退出循环");
				log.error("关闭连接成功---退出循环");
				map.remove(code.getClientOnlyId()); //移除客户端
				return ;
			}
			System.out.println("关闭失败!");
			log.error("关闭失败!");
		}
	}
	/**
	 * 处理指令
	 */
	public void processingInstruction(CodeAttribute code) {
		System.err.println("processingInstruction 处理指令"+code.getClientTypeNumber());
		log.info("processingInstruction 处理指令"+code.getClientTypeNumber());
		if("0000".equalsIgnoreCase(code.getClientTypeNumber())) {
			//wifi模块连接指令
			System.err.println("WIFI端---编号为：["+code.getClientOnlyId() + "] 连接成功...");
			log.info("WIFI端---编号为：["+code.getClientOnlyId() + "] 连接成功...");
		}else if("1111".equalsIgnoreCase(code.getClientTypeNumber())) {
			androidSend(code);  //安卓发送指令
		}else if("2222".equalsIgnoreCase(code.getClientTypeNumber())) {
			//心跳代码
		}else if("3333".equalsIgnoreCase(code.getClientTypeNumber())) {
			//wifi模块执行成功指令的代码
			System.out.println("进入反馈方法");
			log.info("进入反馈方法");
			boolean flag  = feedbackResult(code);
			System.out.println("获取反馈结果"+flag);
			log.info("获取反馈结果"+flag);
		}else if("4444".equalsIgnoreCase(code.getClientTypeNumber())){
			//获取温度
			Integer data;
			try {
				data = Integer.parseInt(code.getTemperature());
			} catch (Exception e1) {
				log.error("温度转换失败" + e1);
				log.info("温度转换失败" + e1);
				return ;
			}
			log.info("温度获取成功,实时温度为: " + data);
			if(data <= 29){
				log.info("温度小于设定值 关闭风扇 " + data);
				new Thread() {  //连接成功后发送反馈信息
					@Override
					public void run() {
						try {
							log.info("给 " + code.getClientOnlyId() + " 发送关闭指令");
							String data = "CLOSE\n";
							OutputStream outputStream = code.getSocket().getOutputStream();
							outputStream.write(data.getBytes("utf-8"));
							outputStream.flush();
						} catch (Exception e) {
							
						}
					}
				}.start();
			}else{
				log.info("温度大于设定值 关闭风扇 " + data);
				new Thread() {  //连接成功后发送反馈信息
					@Override
					public void run() {
						try {
							log.info("给 " + code.getClientOnlyId() + " 发送关闭指令");
							String data = "START\n";
							OutputStream outputStream = code.getSocket().getOutputStream();
							outputStream.write(data.getBytes("utf-8"));
							outputStream.flush();
						} catch (Exception e) {
							
						}
					}
				}.start();
			}
		}else {
			System.out.println("指令错误!");
			log.info("指令错误!");
		}
	}

	/**
	 * 安卓发送数据
	 * @param code
	 * @return
	 */
	public boolean androidSend(CodeAttribute code) {
		//安卓端
		System.err.println("安卓端---编号为：["+code.getClientOnlyId() + "] 连接成功...");
		log.info("安卓端---编号为：["+code.getClientOnlyId() + "] 连接成功...");
		if(code.getInstructionLength() == 4) {
			new Thread() {  //连接成功后发送反馈信息
				@Override
				public void run() {
					try {
						String data = "连接成功\n";
						OutputStream outputStream = code.getSocket().getOutputStream();
						outputStream.write(data.getBytes("utf-8"));
						outputStream.flush();
					} catch (Exception e) {
						System.out.println("给 "+code.getClientOnlyId() + " 反馈信息发送失败" + e);
						log.error("给 "+code.getClientOnlyId() + " 反馈信息发送失败" + e);
					}
				}
			}.start();
		}
		if(code.getSendOnlyId() != null) {  //判断安卓端是否发送指令
			System.err.println("发送给客户端那个机器" + code.getSendOnlyId());
			log.info("发送给客户端那个机器" + code.getSendOnlyId());
			Socket socket = null;
			OutputStream out = null;
			try {
				//获取要发送给那个WIFI模块
				CodeAttribute codes = getMapData(map, code);
				socket  = codes.getSocket(); //获取wifi客户端的socket流
				if(socket == null) {System.out.println("socket为空...发送失败");log.info("socket为空...发送失败");return false;}
				out = socket.getOutputStream();
				String data = code.getSendData();  //获取发送的数据
				data += "\n";
				System.err.println("发送的指令为: "+data);
				log.info("发送的指令为: "+data);
				out.write(data.getBytes("utf-8"));
				out.flush();
				boolean flag = udpateData(map,code);
				System.out.println("更新标识成功..."+ flag);
				log.info("更新标识成功..."+ flag);
			} catch (IOException e) {
				udpateData(map,code);
				System.out.println("出现异常,发送失败..." + e);
				log.error("出现异常,发送失败..." + e);
				socketClose(socket,out);  //关闭socket
				map.remove(code.getClientOnlyId());
			}
		}
		return true;
	}

	/**
	 * 反馈结果
	 */
	public boolean feedbackResult(CodeAttribute code) {
		Socket socket = null;
		boolean flag = false;
		OutputStream outputStream =	null;
		//获取要发送给那个客户端(安卓)
		for (Map.Entry<String,CodeAttribute> entries : map.entrySet()) {
			if(entries.getKey().equals(code.getSendOnlyId())) {
				socket  = entries.getValue().getSocket();  //获取安卓端socket流
				flag  = entries.getValue().getSuccess();
				break;
			}
		}
		try {
			if(socket == null) {return false;}
			String data = code.getSendData();
			data += "\n";
			outputStream = socket.getOutputStream();
			outputStream.write(data.getBytes("utf-8"));
			outputStream.flush();
			//outputStream.close();
		} catch (IOException e) {
			System.out.println("反馈信息发送失败" + e);
			log.error("反馈信息发送失败" + e);
			socketClose(socket,outputStream);
			return false;
		}
		return true;
	}


	/**
	 * 关闭socket
	 * @param socket
	 */
	public boolean socketClose(Closeable... targets) {
		for(Closeable target:targets) {
			try {
				if(null!=target) {
					target.close();
					System.out.println("关闭成功...");
					log.info("关闭成功...");
				}
			}catch(Exception e) {
				System.out.println("关闭连接失败!");
				log.error("关闭连接失败!");
				return false;
			}
		}
		return true;
	}

	/**
	 * 更新map数据
	 * @param map
	 * @param code
	 */
	public boolean udpateData(Map<String,CodeAttribute> map,CodeAttribute code) {
		for (Map.Entry<String,CodeAttribute> entries : map.entrySet()) {
			if(entries.getKey().equals(code.getSendOnlyId())) {
				entries.getValue().setSuccess(true);
				return true;
			}
		}
		return false;
	}
	/**
	 * 获取map客户端编号
	 * @param map
	 * @param code
	 */
	public CodeAttribute getMapData(Map<String,CodeAttribute> map,CodeAttribute code) {
		for (Map.Entry<String,CodeAttribute> entries : map.entrySet()) {
			System.err.println(entries.getKey() + " " + code.getSendOnlyId());
			if(entries.getKey().equals(code.getSendOnlyId())) {  
				return entries.getValue();
			}
		}
		return null;
	}
}
class Heartbeat implements Runnable{
	private Logger log = LogManager.getLogger(Heartbeat.class);
	private Timer timer = new Timer(); //定时操作类
	private SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");//设置日期格式
	private Integer seconds = 120000; //秒数
	private Socket socket = null;
	private Map<String,CodeAttribute> map;
	private OutputStream output;
	public Heartbeat(Map<String, CodeAttribute> map) {
		this.map = map;
	}
	@Override
	public void run() {
		staticTimer();
	}

	public void staticTimer() {
		timer.schedule(new TimerTask(){
			@Override
			public void run() {
				if(map.size() != 0) {
					for (Entry<String, CodeAttribute> entries : map.entrySet()) {
						try {
							socket = entries.getValue().getSocket();
							if(socket != null) {
								String data = df.format(new Date());
								System.out.println(entries.getKey() + "状态 --->" + (entries.getValue().isConnectionStatus() ? "在线":"客户端断开了连接"));
								System.out.println(entries.getValue().hashCode() +" "+ "********服务器给编号为：" + entries.getKey() + " 发送心跳*******时间: " + data);
								log.info(entries.getKey() + "状态 --->" + (entries.getValue().isConnectionStatus() ? "在线":"客户端断开了连接"));
								log.info(entries.getValue().hashCode() +" "+ "********服务器给编号为：" + entries.getKey() + " 发送心跳*******时间: " + data);
								socket.sendUrgentData(0xff);
							}
						} catch (Exception e) {
							boolean flag = socketClose(socket,output); //关闭连接
							entries.getValue().setConnectionStatus(false);
							//map.remove(entries.getKey()); //移除socket
							System.out.println("给 [ " +entries.getKey()+ "] 发送心跳失败 ! " + " " +" 服务器主动关闭socket连接 " + (flag?"成功":"失败"));
							log.error("给 [ " +entries.getKey()+ "] 发送心跳失败 ! " + " " +" 服务器主动关闭socket连接 " + (flag?"成功":"失败"));
						}
					}
					System.out.println("客户端数量为 :" + map.size());
					log.info("客户端数量为 :" + map.size());
				}
			}},1000, seconds);
	}
	/**
	 * 关闭socket
	 * @param socket
	 */
	public boolean socketClose(Closeable... targets) {
		for(Closeable target:targets) {
			try {
				if(null!=target) {
					target.close();
					System.out.println("关闭成功...");
				}
			}catch(Exception e) {
				System.out.println("关闭连接失败!");
				return false;
			}
		}
		return true;
	}
}

/**
 * 定时获取温度类
 * @author Administrator
 *
 */
class Temperature implements Runnable{
	private Logger log = LogManager.getLogger(Heartbeat.class);
	private Timer timer = new Timer(); //定时操作类
	private SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");//设置日期格式
	private Integer seconds = 10000; //秒数
	private Socket socket = null;
	private Map<String,CodeAttribute> map;
	private OutputStream output;
	public Temperature(Map<String, CodeAttribute> map) {
		this.map = map;
	}
	@Override
	public void run() {
		staticTimer();
	}

	public void staticTimer() {
		timer.schedule(new TimerTask(){
			@Override
			public void run() {
				if(map.size() != 0) {
					for (Entry<String, CodeAttribute> entries : map.entrySet()) {
						//给wifi发送获取温度的指令
						if(entries.getKey().equalsIgnoreCase("w-10000")){
							try {
								socket = entries.getValue().getSocket();
								if(socket != null) {
									String data = df.format(new Date());
									log.info("开始准备获取温度 : " + entries.getKey() +" 时间为 :--->" + data);
									output = socket.getOutputStream();
									output.write("D\n".getBytes());
									output.flush();
									break;
								}
							} catch (Exception e) {
								socketClose(socket,output);
							}
						}
					}
				}
			}},2000, seconds);
	}
	/**
	 * 关闭socket
	 * @param socket
	 */
	public boolean socketClose(Closeable... targets) {
		for(Closeable target:targets) {
			try {
				if(null!=target) {
					target.close();
					System.out.println("关闭成功...");
				}
			}catch(Exception e) {
				System.out.println("关闭连接失败!");
				return false;
			}
		}
		return true;
	}
}




